home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / science / cdrift3.zip / IBMPC.C < prev    next >
C/C++ Source or Header  |  1990-02-22  |  23KB  |  719 lines

  1. /* Modified for IBM PC/XT/AT, 9/12/89..9/01/90 from file ami.c:
  2.              Peter C. Lind, M.Sc.,   lind@maccs.ca
  3.              McMaster University,
  4.              1280 Main St. W.,
  5.              Hamilton, ON
  6.              Canada   L8S 4K1
  7.  
  8.    This file contains only functions which are specific to the IBM PC/XT/AT
  9.    under Turbo C 2.00+.  It connects to the other source files via a small
  10.    number of functions. main() is here.  It calls init() and onestep().
  11.    The other source files can call rnd(), draw() and panic() from this file;
  12.    these are at the end of the file. */
  13.  
  14. #include "const.h"
  15. #include "var.h"
  16.  
  17. #include <conio.h>
  18. #include <dos.h>
  19. #include <graphics.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <time.h>
  23.  
  24. #define TRUE !0
  25. #define FALSE 0
  26.  
  27. #define STDOUT_HANDLE 1                  /* DOS file handle for stdout */
  28.  
  29. extern unsigned long RangeSeed;          /* TC random number generator */
  30. extern unsigned char t[2][MAXX][MAXY];   /* Defined in tec1.c */
  31. extern short step;                       /* Also defined in tec1.c */
  32.  
  33. unsigned long         class;
  34. unsigned short        code;
  35.  
  36. /* EGA: 16 colors used: Black, 2 shades of blue (dark, light), 2 of green,
  37.         2 of red, 2 of purple (magenta), 2 white (light gray, white), and
  38.     2 yellow (brown, yellow). */
  39. #define NUMCOLORS 13
  40. #define MAXCOLOR 12
  41. unsigned short colors [NUMCOLORS] = {
  42.                                      BLACK,
  43.                                      BLUE,LIGHTBLUE,GREEN,LIGHTGREEN,
  44.                                      YELLOW,MAGENTA,LIGHTMAGENTA,
  45.                                      RED,LIGHTRED,BROWN,
  46.                                      LIGHTGRAY,WHITE
  47.                                     };
  48.  
  49. unsigned short CellXsize,CellYsize;   /* Size of a tec pixel */
  50. int MaxX,MaxY,CentX,CentY;            /* Screen parameters */
  51. int LastVideoMode;                    /* Video mode at program start up */
  52. int gdriver;                          /* Graphics driver used for plotting */
  53. int BrightColor,DimColor,BorderColor,BackgroundColor,BarColor;
  54. int Bar3Dcolor,PlotBackColor;
  55. int wx1,wy1,wx2,wy2,winMaxX,winMaxY,origY2;  /* Map window coords */
  56.  
  57. int LegCellWid,LegCellHgt,LegHalfWid; /* Legend parameters */
  58. int legX1,legY1,legX2,legY2,legCY;
  59.  
  60. short InColor;                        /* TRUE if mode is EGA or VGA */
  61. short Mode3D;                         /* TRUE when plotting in 3d mode */
  62. short Slow3D;                         /* TRUE for slow 3d plotting */
  63. short AllStop;                        /* TRUE if user wants to quit */
  64. short WantPrint;                      /* TRUE if user wants to print */
  65. short WantPause;                      /* TRUE if user wants to pause */
  66. short WantChangePlot;                 /* TRUE if user wants to change
  67.                                           plotting style */
  68. short NeedLegend;                     /* TRUE if legend should be drawn */
  69. short NoLegend;                       /* TRUE if legend should be erased */
  70.  
  71. int msgY;                             /* Y coord of message line top */
  72.  
  73. #define xaddon 5                      /* Width of 3-d bars */
  74. int ix;                               /* Initial X coord for 3-d */
  75. int iy;                               /* Initial Y coord for 3-d */
  76. int yaddon;                           /* Y increment for 3-d plotting */
  77.  
  78. #define ESC 27                        /* ASCII code for ESC */
  79.  
  80. #define NUM_CREDITS 5
  81. static char title[]   = "TEC   Continental Drift Simulator";
  82. static char credit[NUM_CREDITS][42] =
  83.              {
  84.               "Version  3",
  85.               "originally written by David Allen",
  86.               "adapted for IBM PC/XT/AT by Peter C. Lind",
  87.               "Copyright (c) 1989,1990",
  88.               "press any key to begin"
  89.              };
  90. int CredFont,TitleSize,CredSize;
  91.  
  92. void TakeMax (a,b)
  93.  /* `a' gets maximum of `a' and `b'. */
  94.  int *a,b;
  95.   {
  96.    if (b > *a)
  97.       *a = b;
  98.   }
  99.  
  100. void panic (s)
  101.  char *s;
  102.  /* Used when some fatal inconsistency is found in the database;
  103.     its function is to immediately free all graphics memory and exit. */
  104.   {
  105.    closegraph();
  106.    textmode(LastVideoMode);
  107.    printf("TEC PANIC: %s\n",s);
  108.    exit(0);
  109.   }
  110.  
  111. void message (s)
  112.  char *s;
  113.  /* Displays message `s' at the bottom of the screen. */
  114.   {
  115.    struct viewporttype ov;
  116.  
  117.    getviewsettings(&ov);                       /* Save current viewport */
  118.    setviewport(0,0,MaxX,MaxY,TRUE);            /* Select entire screen */
  119.    setfillstyle(SOLID_FILL,BarColor);
  120.    bar(0,msgY,MaxX,MaxY);                      /* Blank bottom line */
  121.    settextjustify(CENTER_TEXT,TOP_TEXT);
  122.    setcolor(DimColor);
  123.    outtextxy(CentX,msgY+1,s);                  /* Output message */
  124.    setviewport(ov.left,ov.top,ov.right,        /* Select old viewport */
  125.                ov.bottom,ov.clip);
  126.   }
  127.  
  128. void WaitKeyPress ()
  129.  /* Wait for user to press a key. */
  130.   {
  131.    while (!kbhit())
  132.          ;
  133.    if (!(getch()))              /* Consume any extended code */
  134.       getch();
  135.   }
  136.  
  137. void Intro ()
  138.  /* Displays the introductory credits panel. */
  139.   {
  140.    int th,tw,x1,y1,x2,y2,y,ht,hc,cx,i,TwoEms;
  141.  
  142.    /* Calculate dimensions of panel required */
  143.    settextstyle(CredFont,HORIZ_DIR,TitleSize);    /* Measure title line */
  144.    ht = textheight(title); th = (ht * 3);
  145.    tw = textwidth(title) + (textwidth("M") << 1);
  146.    settextstyle(CredFont,HORIZ_DIR,CredSize);     /* Measure credit lines */
  147.    TwoEms = textwidth("M") << 1;
  148.    hc = 0;
  149.    for (i = 0; i < NUM_CREDITS; i++)              /* Find max. height, width */
  150.        {
  151.     TakeMax(&hc,textheight(credit[i]));
  152.         TakeMax(&tw,textwidth(credit[i])+TwoEms);
  153.        }
  154.    hc <<= 1;
  155.    th += (hc * NUM_CREDITS);
  156.    x1 = (MaxX - tw) >> 1; x2 = x1 + tw - 1;
  157.    y1 = (MaxY - th) >> 1; y2 = y1 + th - 1;
  158.    cx = (tw >> 1) - 1;
  159.  
  160.    /* Draw panel and display title and credits */
  161.    setfillstyle(SOLID_FILL,BarColor); setcolor(BarColor);
  162.    bar3d(x1,y1,x2,y2,4,TRUE);
  163.    setviewport(x1+1,y1+1,x2-1,y2-1,TRUE);
  164.    y = ht;
  165.    settextstyle(CredFont,HORIZ_DIR,TitleSize);
  166.    settextjustify(CENTER_TEXT,TOP_TEXT);
  167.    setcolor(BrightColor);
  168.    outtextxy(cx,y,title);
  169.    y += (ht << 1);
  170.    settextstyle(CredFont,HORIZ_DIR,CredSize);
  171.    for (i = 0; i < NUM_CREDITS; i++, y += hc)
  172.        outtextxy(cx,y,credit[i]);
  173.    WaitKeyPress();
  174.    setviewport(0,0,MaxX,MaxY,TRUE);
  175.    cleardevice();
  176.   }
  177.  
  178. void CGAdefaults ()
  179.  /* Common routine to set CGA/MCGA defaults. */
  180.   {
  181.    BarColor = 1; BrightColor = 0; DimColor = 0;
  182.    BorderColor = 1; BackgroundColor = 0; Bar3Dcolor = 1; PlotBackColor = 0;
  183.    InColor = FALSE; Mode3D = TRUE; Slow3D = FALSE;
  184.   }
  185.  
  186. int initCGA ()
  187.  /* Initialize CGA mode. */
  188.   {
  189.    CGAdefaults();
  190.    CredFont = SMALL_FONT; TitleSize = 6; CredSize = 4;
  191.    return(CGAHI);
  192.   }
  193.  
  194. int initMCGA ()
  195.  /* Initialize MCGA mode. */
  196.   {
  197.    CGAdefaults();
  198.    CredFont = SMALL_FONT; TitleSize = 6; CredSize = 4;
  199.    return(MCGAHI);
  200.   }
  201.  
  202. void EGAdefaults ()
  203.  /* Common routine to set EGA/VGA defaults. */
  204.   {
  205.    BarColor = DARKGRAY; BrightColor = WHITE; DimColor = LIGHTGRAY;
  206.    PlotBackColor = BLACK;
  207.    BorderColor = DARKGRAY; BackgroundColor = BLACK; Bar3Dcolor = LIGHTGRAY;
  208.    InColor = TRUE; Mode3D = FALSE;
  209.    LegCellWid = 20; LegHalfWid = 10;
  210.    NeedLegend = TRUE;
  211.   }
  212.  
  213. int initEGA ()
  214.  /* Initialize EGA */
  215.   {
  216.    EGAdefaults();
  217.    CellXsize = 7; CellYsize = 3;
  218.    CredFont = TRIPLEX_FONT; TitleSize = 3; CredSize = 2;
  219.    LegCellHgt = 16;
  220.    return(EGAHI);
  221.   }
  222.  
  223. int initVGA ()
  224.  /* Initialize VGA */
  225.   {
  226.    EGAdefaults();
  227.    CellXsize = 7; CellYsize = 5;
  228.    CredFont = TRIPLEX_FONT; TitleSize = 4; CredSize = 3;
  229.    LegCellHgt = 16;
  230.    return(VGAHI);
  231.   }
  232.  
  233. void grafinit ()
  234.  /* Detect the video hardware and configure accordingly; display credits */
  235.   {
  236.    int gm,tw,th,rc;
  237.  
  238.    LastVideoMode = LASTMODE;
  239.    detectgraph(&gdriver,&gm);
  240.    switch (gdriver)
  241.       {
  242.            case CGA: gm = initCGA();   /* CGA high-res mode: 640 x 200, 2 colors */
  243.                      break;
  244.            case MCGA: gm = initMCGA(); /* MCGA high-res mode: 640 x 480, 2 colors */
  245.                       break;
  246.        case EGA: gm = initEGA();   /* EGA high-res mode: 640 x 350, 16 colors */
  247.                      break;
  248.        case VGA: gm = initVGA();   /* VGA high-res mode: 640 x 480, 16 colors */
  249.                      break;
  250.            default: printf("TEC 3:\n");
  251.                     printf("Unable to operate with detected display type\n");
  252.                     printf("Require CGA, MCGA, EGA or VGA to run\n");
  253.                     exit(0);
  254.       }
  255.    initgraph(&gdriver,&gm,"");
  256.    if ((rc = graphresult()))
  257.       {
  258.        printf("TEC 3:\n");
  259.        printf("BGI Error #%d: %s\n",rc,grapherrormsg(rc));
  260.        textmode(LastVideoMode);
  261.        exit(0);
  262.       }
  263.    MaxX = getmaxx(); MaxY = getmaxy();
  264.    CentX = MaxX >> 1; CentY = MaxY >> 1;
  265.    Intro();                                             /* Intro panel */
  266.    settextstyle(DEFAULT_FONT,HORIZ_DIR,1);              /* Choose font */
  267.    tw = textwidth("M"); th = textheight("M");           /* Font's dimensions */
  268.    msgY = MaxY - th - 2;
  269.  
  270.    setfillstyle(SOLID_FILL,BarColor); bar(0,0,MaxX,th+1); /* Top bar */
  271.    bar(0,msgY,MaxX,MaxY);                                 /* Bottom bar */
  272.    setcolor(BrightColor);
  273.    settextjustify(LEFT_TEXT,TOP_TEXT);
  274.    moveto(tw,1); outtext("TEC ");
  275.    setcolor(DimColor); outtext("Continental Drift Simulator");
  276.    settextjustify(RIGHT_TEXT,TOP_TEXT);
  277.    outtextxy(MaxX-tw,1,"David Allen, Peter C. Lind");
  278.  
  279.    setcolor(BorderColor); rectangle(0,th+1,MaxX,msgY);    /* Map border */
  280.    wx1 = 2; wy1 = th + 3; wx2 = MaxX - 2; wy2 = msgY - 2;
  281.    winMaxX = wx2 - wx1; winMaxY = wy2 - wy1; origY2 = wy2;
  282.  
  283.    legX2 = winMaxX; legX1 = legX2 - (LegCellWid * NUMCOLORS); /* Legend coords */
  284.    legY2 = winMaxY - 1; legY1 = legY2 - LegCellHgt;
  285.    legCY = (legY2 + legY1) >> 1;
  286.  
  287.    setviewport(wx1,wy1,wx2,wy2,TRUE);
  288.  
  289.    ix = (wx2 - wx1) - (XSIZE * xaddon);
  290.    yaddon = ((wy2 - wy1 + 1) / YSIZE) + 1;
  291.    iy = (wy2 - wy1 + 1) - (YSIZE * yaddon);
  292.   }
  293.  
  294. void grafexit ()
  295.  /* Just close all the things that were opened, then exit(). */
  296.   {
  297.    closegraph();
  298.    textmode(LastVideoMode);
  299.    printf("TEC ended. Bye\n");
  300.    exit(0);
  301.   }
  302.  
  303. unsigned GetIOCTL (fh)
  304.  /* Returns the IOCTL word for file handle `fh'. */
  305.  int fh;
  306.   {
  307.    struct REGPACK regs;
  308.  
  309.    regs.r_ax = 0x4400;            /* DOS Int. sub-function: "Get IOCTL info" */
  310.    regs.r_bx = fh;                /* File handle in BX */
  311.    intr(33,®s);                /* Call DOS */
  312.    return(regs.r_dx);             /* IOCTL info in DX */
  313.   }
  314.  
  315. void PrintMenu ()
  316.  /* Displays the print menu. */
  317.   {
  318.    message("Print to stdout:  G)eneric  T)ext  P)ostscript  ESC=No print");
  319.   }
  320.  
  321. void TryToPrint ()
  322.  /* Attempts to initiate printing, but first warns the user that stdout
  323.     must have been redirected on the DOS command line. Also allows the
  324.     user to choose the print format:
  325.  
  326.                    G    Generic
  327.                    T    Text
  328.                    P    Postscript
  329.                   ESC   No print
  330.  */
  331.   {
  332.    /* Disallow printing if stdout is still directed to the console screen,
  333.       (ie. IOCTL for stdout indicates device with standard console output). */
  334.    if ((GetIOCTL(STDOUT_HANDLE) & 0x0082) == 0x0082)
  335.       {
  336.        message("*** stdout not redirected.  [ Press any key ] ***");
  337.        do {                        /* Wait for keypress */
  338.           } while (!kbhit());
  339.        if (!getch())               /* Consume character */
  340.           getch();                 /*   and extended code, if any */
  341.        return;
  342.       }
  343.  
  344.    PrintMenu();
  345.    do {
  346.        char c;
  347.  
  348.        if (!(c = getch()))
  349.           getch();
  350.          else
  351.           switch (c)
  352.                  {
  353.                   case ESC: return;
  354.                             break;
  355.                   case 'g':
  356.                   case 'G': message("Sending Generic Mode to stdout...");
  357.                             tecst(step % 2,DRAWMODE_GENERIC);
  358.                             PrintMenu();
  359.                             break;
  360.                   case 't':
  361.                   case 'T': message("Sending Text Mode to stdout...");
  362.                             tecst(step % 2,DRAWMODE_TEXT);
  363.                             PrintMenu();
  364.                             break;
  365.                   case 'p':
  366.                   case 'P': message("Sending Postscript Mode to stdout...");
  367.                             tecst(step % 2,DRAWMODE_GRAY);
  368.                             PrintMenu();
  369.                             break;
  370.                   default: break;
  371.                  }
  372.       } while (TRUE);
  373.   }
  374.  
  375. void Set3Dstyle ()
  376.  /* Allows user to choose fast or slow 3-D plotting. */
  377.   {
  378.    short OK;
  379.  
  380.    Mode3D = TRUE;
  381.    message("3-D Style: S)low  F)ast");
  382.    do {
  383.        OK = TRUE;
  384.        switch (getch())
  385.               {
  386.                case 's':
  387.                case 'S': Slow3D = TRUE;
  388.                          break;
  389.                case 'f':
  390.                case 'F': Slow3D = FALSE;
  391.                          break;
  392.                default: OK = FALSE;
  393.                         break;
  394.               }
  395.       } while (!OK);
  396.   }
  397.  
  398. void ChangePlotStyle ()
  399.  /* Allows user to switch between standard plotting and 3-D plotting. Should
  400.     only be called if program is running under EGA/VGA. */
  401.   {
  402.    short OK;
  403.  
  404.    message("Switch plotting style:  S)tandard  3)D");
  405.    do {
  406.        OK = TRUE;
  407.        switch (getch())
  408.               {
  409.                case '\0': getch();
  410.                           break;
  411.                case '3': NoLegend = !Mode3D;
  412.                          Set3Dstyle();
  413.                          break;
  414.                case 's':
  415.                case 'S': NeedLegend = Mode3D;
  416.                          Mode3D = FALSE;
  417.                          break;
  418.                default: OK = FALSE;
  419.                         break;
  420.               }
  421.       } while (!OK);
  422.   }
  423.  
  424. void checkmouse ()
  425.  /* Standard event handler. Currently on the IBM PC/XT/AT, can only poll the
  426.     keyboard for user actions (no mouse support [yet!]):
  427.  
  428.            <ESC>      Quit program right away
  429.           <SPACE>     Pause
  430.           g or G      Change plotting style
  431.           p or P      Print out the current values of t[src]
  432.                       using tecst() in tec1.c. */
  433.   {
  434.    short i,j,k;
  435.    char c;
  436.  
  437.    if (!kbhit())                  /* Key pressed? */
  438.       return;                     /*   No: Exit */
  439.    if (!(c = getch()))            /* Read the key. Is it '\0'? */
  440.       {
  441.        getch(); return;           /*   Yes: Consume extended code and exit */
  442.       }
  443.    switch (c)                     /*   No: Look at key pressed */
  444.           {
  445.            case ESC: grafexit();
  446.                      break;
  447.            case ' ': WantPause = TRUE;
  448.                      break;
  449.            case 'g':
  450.            case 'G': if (InColor)
  451.                         ChangePlotStyle();
  452.                        else
  453.                         Set3Dstyle();
  454.                      break;
  455.            case 'p':
  456.            case 'P': TryToPrint();
  457.                      break;
  458.            default: break;
  459.           }
  460.   }
  461.  
  462. int rnd (top)
  463.  int top;
  464.  /* Returns a random number in the range 0..`top'-1. */
  465.   {
  466.    return(random(top));
  467.   }
  468.  
  469. void ResetPlotSettings ()
  470.  /* Resets the 3-D plot settings (used after message() calls). */
  471.   {
  472.    if (Mode3D)
  473.       {
  474.        setfillstyle(SOLID_FILL,PlotBackColor);
  475.        setcolor(Bar3Dcolor);
  476.       }
  477.   }
  478.  
  479. void PlotMessage ()
  480.  /* Prints the plot message */
  481.   {
  482.    message("Plotting...  G)raphing style  P)rint  CR=Skip  SP=Pause  ESC=Quit");
  483.   }
  484.  
  485. int PlotKeyCheck ()
  486.  /* Called when a key is pressed while plotting. If the key was ESC or
  487.     SPACE, then TRUE is returned. Otherwise, FALSE is returned. If the
  488.     key pressed was ESC, 'p' or 'P', the key is not consumed. */
  489.   {
  490.    char c;
  491.  
  492.    switch (c = getch())
  493.           {
  494.            case '\0': getch();            /* Discard extended code */
  495.                       break;
  496.            case ESC: AllStop = TRUE;      /* Set quit flag... */
  497.            case '\r': return(TRUE);       /* Exit plot routine */
  498.                       break;
  499.            case ' ': WantPause = TRUE;
  500.                      break;
  501.            case 'g':
  502.            case 'G': if (InColor)         /* Defer in EGA/VGA */
  503.                         WantChangePlot = TRUE;
  504.                        else
  505.                         {                 /* Change on the fly in CGA/MCGA */
  506.                          Set3Dstyle();
  507.                          PlotMessage();
  508.                          ResetPlotSettings();
  509.                         }
  510.                      break;
  511.            case 'p':
  512.            case 'P': WantPrint = TRUE;    /* Set print request flag */
  513.                      break;
  514.            default: break;                /* Ignore all else */
  515.           }
  516.    return(FALSE);
  517.   }
  518.  
  519. void draw3d (src)
  520.  /* Draws a 3-D picture of the t[src] in the center of the current viewport
  521.     using Turbo C's bar3d() function. When `Slow3D' is TRUE, each "pixel" of
  522.     t[src] is printed as a standing 3-D block; when `Slow3D' is FALSE,
  523.     adjacent "pixels" in the same row with equal heights are merged and
  524.     plotted as a wider standing 3-D block, thereby speeding up the plotting
  525.     process (with a loss of attractiveness). */
  526.  short src;
  527.   {
  528.    int boty,x1,x2,x3,x,y,cx,cy,h,nh,c;
  529.  
  530.    ResetPlotSettings();
  531.  
  532.    x = ix; y = iy;
  533.    top: for (cx = 0; cx < XSIZE; cx++, y += yaddon)
  534.             {
  535.              x1 = x; x2 = x1 + xaddon; x3 = x + (xaddon * XSIZE);
  536.              h = -1; c = 0;
  537.              for (cy = 0; cy < YSIZE; cy++)
  538.                  {
  539.                   nh = t[src][cx][cy] >> 3;
  540.                   if ((nh != h) || Slow3D)
  541.                      {
  542.                       if ((c || Slow3D) && (h >= 0))
  543.                          bar3d(x1,y,x2,y-h,3,TRUE);
  544.                       h = nh; x1 = x2; c = 1;
  545.                       if (Slow3D || 1)
  546.                          x2 += xaddon;
  547.                      }
  548.                     else
  549.                      {
  550.                       x2 += xaddon; c++;
  551.                      }
  552.                  }
  553.              if (c)
  554.                 bar3d(x1,y,x3,y-nh,3,TRUE);
  555.              x -= (xaddon >> 1);
  556.  
  557.              if (kbhit())
  558.                 if (PlotKeyCheck())
  559.                    return;
  560.             }
  561.   }
  562.  
  563. void DisplayLegend ()
  564.  /* Draws the colors legend for EGA/VGA modes. */
  565.   {
  566.    int i,x;
  567.    char num[3];
  568.  
  569.    settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
  570.    settextjustify(CENTER_TEXT,CENTER_TEXT);
  571.  
  572.    /* Special case for black color */
  573.    x = legX1;
  574.    setcolor(DARKGRAY);
  575.    setfillstyle(SOLID_FILL,colors[0]);
  576.    bar3d(x,legY1,x+LegCellWid,legY2,0,FALSE);
  577.    outtextxy(x+LegHalfWid,legCY,"0");
  578.    x += LegCellWid;
  579.  
  580.    /* Draw other colors in a loop, with black numbers */
  581.    setcolor(BLACK);
  582.    for (i = 1; i < NUMCOLORS; i++, x += LegCellWid)
  583.        {
  584.         setfillstyle(SOLID_FILL,colors[i]);
  585.         bar3d(x,legY1,x+LegCellWid,legY2,0,FALSE);
  586.         sprintf(num,"%d",i);
  587.         outtextxy(x+LegHalfWid,legCY,num);
  588.        };
  589.    wy2 = origY2 - LegCellHgt - 2;       /* Resize viewport to protect legend */
  590.    setviewport(wx1,wy1,wx2,wy2,TRUE);
  591.   }
  592.  
  593. void RemoveLegend ()
  594.  /* Effectively removes the colors legend by resetting the map viewport to
  595.     full size. */
  596.   {
  597.    wy2 = origY2; setviewport(wx1,wy1,wx2,wy2,TRUE);
  598.   }
  599.  
  600. void draw (src)
  601.  short src;
  602.  /* When `Mode3D' is TRUE, this function calls draw3d() and exits. Otherwise,
  603.     this function takes the array m[src] and draws it on the screen, in a
  604.     hopefully efficient way.  The function tries to make long horizontal
  605.     patches that are all the same color.  Then they can be rendered by a
  606.     graphics function that draws arbitrary rectangles quickly. */
  607.   {
  608.    register short i,j,k,x;
  609.  
  610.    checkmouse();
  611.    PlotMessage();
  612.  
  613.    /* Erase the viewport first */
  614.    if (NoLegend)
  615.       {
  616.        RemoveLegend(); NoLegend = FALSE;
  617.       }
  618.    setcolor(BackgroundColor); clearviewport();
  619.  
  620.    if (Mode3D)                  /* If in 3-D mode, then call draw3d() */
  621.       {
  622.        draw3d(src); return;
  623.       }
  624.  
  625.    /* Draw color legend whenever it needs to be displayed. */
  626.    if (NeedLegend)
  627.       {
  628.        DisplayLegend(); NeedLegend = FALSE;
  629.       }
  630.  
  631.    /* For each scan line, start at the left edge */
  632.    for (j = 0, i = 0; j < YSIZE; j++, i = 0)
  633.        {
  634.         int x1,y1,x2,y2;
  635.  
  636.     /* If the current square is not ocean, set x to its color */
  637.     top: if ((x = t[src][i][j] >> 2) > 1)
  638.                 {
  639.                  /* Go as far along to the right as you can in this color */
  640.                  k = i + 1;
  641.                  while (((t[src][k][j] >> 2) == x) && (k < XSIZE-1))
  642.                        k++;
  643.  
  644.                  /* Draw a short, wide rectangle */
  645.                  if (x > 27)
  646.                     x = 27;
  647.                  x1 = i * CellXsize; y1 = j * CellYsize;
  648.                  x2 = k * CellXsize; y2 = y1 + CellYsize - 1;
  649.                  setfillstyle(SOLID_FILL,colors[x]);
  650.                  bar(x1,y1,x2,y2);
  651.                  i = k-1;
  652.  
  653.                  if (kbhit())
  654.                     if (PlotKeyCheck())
  655.                        return;
  656.                 }
  657.  
  658.         /* If not at end of scanline, do more; else start next scanline */
  659.         if (i < XSIZE-1)
  660.            {
  661.             i++;
  662.             goto top;
  663.            }
  664.        }
  665.   }
  666.  
  667. void main (argc,argv)
  668.  /* Initializes everything and enters a (finite) loop that repeatedly calls
  669.     onestep() and checkmouse() until the maximum step is reached or the user
  670.     quits. */
  671.  int argc;
  672.  char **argv;
  673.   {
  674.    char menu[80];
  675.  
  676.    randomize();     /* Randomize random number generator using DOS time */
  677.  
  678.    /* Initialize everything */
  679.    AllStop = WantPrint = WantPause = WantChangePlot = FALSE; /* Clear deferrals */
  680.    NoLegend = FALSE;
  681.    grafinit();
  682.    message("Setting up...");
  683.    init(*++argv);                 /* Perform major initialization */
  684.    checkmouse();                  /* Give user a chance to do something */
  685.  
  686.    /* Call onestep() once per step; then check for user key actions */
  687.    for (step = 0; step < MAXSTEP; step++)
  688.        {
  689.         /* Check for deferred commands */
  690.         if (AllStop)
  691.            grafexit();
  692.         if (WantPrint)
  693.            TryToPrint();
  694.         if (WantChangePlot)
  695.            ChangePlotStyle();
  696.         if (WantPause)
  697.            {
  698.             message("[ Pausing -- Press any Key ]");
  699.             WaitKeyPress();
  700.            }
  701.         WantPrint = WantPause = WantChangePlot = FALSE;  /* Clear deferrals */
  702.  
  703.         /* Do some work */
  704.         sprintf(menu,"Thinking [%d]... G)raphing style  P)rint  SP=Pause  ESC=Quit",
  705.                      step);
  706.     message(menu);
  707.         onestep();
  708.         checkmouse();
  709.        }
  710.  
  711.    /* Reached end of simulation without error or user quit signal. */
  712.    message("Execution terminated -- Press any key");
  713.  
  714.    WaitKeyPress();              /* Loop forever until user pressed a key */
  715.  
  716.    closegraph();                /* Shut down */
  717.    textmode(LastVideoMode);
  718.   }
  719.